package com.boarsoft.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import com.boarsoft.common.Util;

public class DateUtil {
	public static final Map<String, Pattern> patterns = new HashMap<>();

	/** yyyy-MM-dd */
	public static final String PATTERN_STDDF = //
			"(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))"
					+ "|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])"
					+ "|((0[48]|[2468][048]|[3579][26])00))-02-29)$";
	/** yyyy-MM-dd HH:mm:ss */
	public static final String PATTERN_STDDTF = //
			"^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))"
					+ "|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])"
					+ "|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
	/** yyyy-MM-dd HH:mm:ss.SSS */
	public static final String PATTERN_STDDTMF = //
			"^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))"
					+ "|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])"
					+ "|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"
					+ "\\.([0-9]{3})$";
	/** yyyyMMdd */
	public static final String PATTERN_STDDF2 = //
			"(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))"
					+ "|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"
					+ "((0[48]|[2468][048]|[3579][26])00))0229)$";
	/** yyyyMMddHHmmss */
	public static final String PATTERN_STDDTF2 = //
			"((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))"
					+ "|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])"
					+ "|((0[48]|[2468][048]|[3579][26])00))0229))([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$";
	/** yyyyMMddHHmmssSSS */
	public static final String PATTERN_STDDTMF2 = //
			"((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
					+ "(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))"
					+ "|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"
					+ "((0[48]|[2468][048]|[3579][26])00))0229))([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])"//
					+ "([0-9]{3})$";
	/** yyyy/MM/dd */
	public static final String PATTERN_STDDF3 = //
			"(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\\/"
					+ "(((0[13578]|1[02])\\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)\\/(0[1-9]|[12][0-9]|30))"
					+ "|(02\\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"
					+ "((0[48]|[2468][048]|[3579][26])00))\\/02\\/29)$";
	/** yyyy/MM/dd HH:mm:ss */
	public static final String PATTERN_STDDTF3 = //
			"((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\\/"
					+ "(((0[13578]|1[02])\\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)\\/(0[1-9]|[12][0-9]|30))"
					+ "|(02\\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"
					+ "((0[48]|[2468][048]|[3579][26])00))\\/02\\/29))\\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
	/** yyyy/MM/dd HH:mm:ss.SSS */
	public static final String PATTERN_STDDTMF3 = //
			"((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\\/"
					+ "(((0[13578]|1[02])\\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)\\/(0[1-9]|[12][0-9]|30))"
					+ "|(02\\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"
					+ "((0[48]|[2468][048]|[3579][26])00))\\/02\\/29))\\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"
					+ "\\.([0-9]{3})$";

	static {
		patterns.put(Util.STDDF, Pattern.compile(PATTERN_STDDF));
		patterns.put(Util.STDDF2, Pattern.compile(PATTERN_STDDF2));
		patterns.put(Util.STDDF2, Pattern.compile(PATTERN_STDDF3));
		patterns.put(Util.STDDTF, Pattern.compile(PATTERN_STDDTF));
		patterns.put(Util.STDDTF2, Pattern.compile(PATTERN_STDDTF2));
		patterns.put(Util.STDDTF3, Pattern.compile(PATTERN_STDDTF3));
		patterns.put(Util.STDDTMF, Pattern.compile(PATTERN_STDDTMF));
		patterns.put(Util.STDDTMF2, Pattern.compile(PATTERN_STDDTMF2));
		patterns.put(Util.STDDTMF3, Pattern.compile(PATTERN_STDDTMF3));
	}

	public enum DatePart {
		YEAR(1), MONTH(2), WEEK(3), DAY(4), HOUR(5), MIN(6), SEC(7), MILL(8);
		// YEAR, MONTH, WEEK, DAY, HOUR, MIN, SEC, MILL;

		private int intValue;

		private DatePart() {
		}

		private DatePart(int i) {
			this.intValue = i;
		}

		public int getIntValue() {
			return intValue;
		}

		public void setIntValue(int intValue) {
			this.intValue = intValue;
		}

	}

	private DateUtil() {
	}

	/**
	 * 计算日期差值<br>
	 * 注意：0601 23:59:59 和 0602 00:00:00 之间相差一天
	 * 
	 * @param startDate
	 * @param endDate
	 * @param datePart
	 * @return
	 */
	public static long dateDiff(Date startDate, Date endDate, DatePart datePart) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(startDate);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(endDate);
		long d = 0;
		if (datePart == DatePart.HOUR || datePart == DatePart.MIN || datePart == DatePart.SEC) {
			d = (c1.getTimeInMillis() - c2.getTimeInMillis()) / 1000;
		} else {
			d = getDaysBetween(c1.getTime(), c2.getTime());
			d = c1.after(c2) ? -d : d;
		}
		switch (datePart) {
		case HOUR:
			return d / 3600;
		case MIN:
			return d / 60;
		case SEC:
			return d;
		case DAY:
			return d;
		case WEEK:
			int w1 = c1.get(Calendar.DAY_OF_WEEK);
			int w2 = c2.get(Calendar.DAY_OF_WEEK);
			long w = d / 7L;
			return (w1 > w2) ? w + 1 : w;
		case MONTH:
			return Math.round(d / 30.4375f);
		case YEAR:
			return d / 365;
		default:
			break;
		}
		return 0;
	}

	/**
	 * 计算日期差值
	 * 
	 * @param sf
	 * @param startDate
	 * @param endDate
	 * @param datePart
	 * @return
	 */
	public static long dateDiff(String sf, String startDate, String endDate, DatePart datePart) {
		return dateDiff(Util.str2date(startDate, sf), Util.str2date(endDate, sf), datePart);
	}

	/**
	 * 当年是否闰年
	 * 
	 * @return
	 */
	public static boolean isLeapYear() {
		return isLeapYear(Calendar.getInstance().get(Calendar.YEAR));
	}

	/**
	 * 是否闰年
	 * 
	 * @param year
	 * @return
	 */
	public static boolean isLeapYear(int year) {
		if ((year % 400) == 0) {
			return true;
		} else if ((year % 4) == 0) {
			if ((year % 100) == 0) {
				return false;
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	/**
	 * 取得指定日期的上一个月的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfPrevMonth(Date date) {
		return DateUtil.getFirstDayOfMonth(DateUtil.addMonth(date, -1));
	}

	/**
	 * 取得指定日期的上一个月的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfPrevMonth(Date date) {
		return DateUtil.getLastDayOfMonth(DateUtil.addMonth(date, -1));
	}

	/**
	 * 取得指定日期的下一个月的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfNextMonth(Date date) {
		return DateUtil.getFirstDayOfMonth(DateUtil.addMonth(date, 1));
	}

	/**
	 * 取得指定日期的下一个月的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfNextMonth(Date date) {
		return DateUtil.getLastDayOfMonth(DateUtil.addMonth(date, 1));
	}

	/**
	 * 取得指定日期的上一个星期的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfPrevWeek(Date date) {
		return DateUtil.getFirstDayOfWeek(DateUtil.addWeek(date, -1));
	}

	/**
	 * 取得指定日期的上一个星期的最后一天
	 * 
	 * @param date
	 *            指定日期。
	 * @return 指定日期的下一个星期的最后一天
	 */
	public static Date getLastDayOfPrevWeek(Date date) {
		return DateUtil.getLastDayOfWeek(DateUtil.addWeek(date, -1));
	}

	/**
	 * 取得指定日期的下一个星期的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfNextWeek(Date date) {
		return DateUtil.getFirstDayOfWeek(DateUtil.addWeek(date, 1));
	}

	/**
	 * 取得指定日期的下一个星期的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfNextWeek(Date date) {
		return DateUtil.getLastDayOfWeek(DateUtil.addWeek(date, 1));
	}

	/**
	 * 取得指定日期的所处星期的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date) {
		/**
		 * 详细设计： 1.如果date是星期日，则加6天 2.如果date是星期一，则加5天 3.如果date是星期二，则加4天
		 * 4.如果date是星期三，则加3天 5.如果date是星期四，则加2天 6.如果date是星期五，则加1天
		 * 7.如果date是星期六，则加0天
		 */
		Calendar gc = Calendar.getInstance();
		gc.setTime(date);
		switch (gc.get(Calendar.DAY_OF_WEEK)) {
		case (Calendar.SUNDAY):
			gc.add(Calendar.DATE, 6);
			break;
		case (Calendar.MONDAY):
			gc.add(Calendar.DATE, 5);
			break;
		case (Calendar.TUESDAY):
			gc.add(Calendar.DATE, 4);
			break;
		case (Calendar.WEDNESDAY):
			gc.add(Calendar.DATE, 3);
			break;
		case (Calendar.THURSDAY):
			gc.add(Calendar.DATE, 2);
			break;
		case (Calendar.FRIDAY):
			gc.add(Calendar.DATE, 1);
			break;
		case (Calendar.SATURDAY):
			gc.add(Calendar.DATE, 0);
			break;
		}
		return gc.getTime();
	}

	/**
	 * 取得指定日期的所处星期的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date) {
		/**
		 * 详细设计： 1.如果date是星期日，则减0天 2.如果date是星期一，则减1天 3.如果date是星期二，则减2天
		 * 4.如果date是星期三，则减3天 5.如果date是星期四，则减4天 6.如果date是星期五，则减5天
		 * 7.如果date是星期六，则减6天
		 */
		Calendar gc = Calendar.getInstance();
		gc.setTime(date);
		switch (gc.get(Calendar.DAY_OF_WEEK)) {
		case (Calendar.SUNDAY):
			gc.add(Calendar.DATE, 0);
			break;
		case (Calendar.MONDAY):
			gc.add(Calendar.DATE, -1);
			break;
		case (Calendar.TUESDAY):
			gc.add(Calendar.DATE, -2);
			break;
		case (Calendar.WEDNESDAY):
			gc.add(Calendar.DATE, -3);
			break;
		case (Calendar.THURSDAY):
			gc.add(Calendar.DATE, -4);
			break;
		case (Calendar.FRIDAY):
			gc.add(Calendar.DATE, -5);
			break;
		case (Calendar.SATURDAY):
			gc.add(Calendar.DATE, -6);
			break;
		}
		return gc.getTime();
	}

	/**
	 * 取得指定日期的所处月份的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar gc = Calendar.getInstance();
		gc.setTime(date);
		gc.set(Calendar.DAY_OF_MONTH, getMaxDayOfMonth(date));
		// 检查闰年
		if ((gc.get(Calendar.MONTH) == Calendar.FEBRUARY) && (isLeapYear(gc.get(Calendar.YEAR))))
			gc.set(Calendar.DAY_OF_MONTH, 29);
		return gc.getTime();
	}

	/**
	 * 取得指定日期的所处月份的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar gc = Calendar.getInstance();
		gc.setTime(date);
		gc.set(Calendar.DAY_OF_MONTH, 1);
		return gc.getTime();
	}

	/**
	 * 取得指定日期的所处年的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfYear(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.MONTH, 11);
		c.set(Calendar.DATE, 31);
		return c.getTime();
	}

	/**
	 * 取得指定日期的所处年的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfYear(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.MONTH, 0);
		c.set(Calendar.DATE, 1);
		return c.getTime();
	}

	/**
	 * 获取日期间隔天数<br>
	 * 注意：此方法总是返回绝对值，且0601 23:59:59 和 0602 00:00:00 之间相差一天
	 * 
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int getDaysBetween(Date d1, Date d2) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(d1);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
		// swap dates so that d1 is start and d2 is end
		if (d1.after(d2)) {
			Calendar swap = c1;
			c1 = c2;
			c2 = swap;
		}
		int days = c2.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
		int y2 = c2.get(Calendar.YEAR);
		if (c1.get(Calendar.YEAR) != y2) {
			c1 = (Calendar) c1.clone();
			do {
				days += c1.getActualMaximum(Calendar.DAY_OF_YEAR);// 得到当年的实际天数
				c1.add(Calendar.YEAR, 1);
			} while (c1.get(Calendar.YEAR) != y2);
		}
		return days;
	}

	public static int getDayOfWeek(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(7);
	}

	public static int getDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(5);
	}

	/**
	 * 当月最大天数
	 * 
	 * @param date
	 * @return
	 */
	public static int getMaxDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	public static int getDayOfYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(6);
	}

	public static Date addSecond(Date date, long count) {
		return new Date(date.getTime() + 1000L * count);
	}

	public static Date addMillSecond(Date date, long count) {
		return new Date(date.getTime() + count);
	}

	public static Date addMinute(Date date, int count) {
		return new Date(date.getTime() + 60000L * (long) count);
	}

	public static Date addHour(Date date, int count) {
		return new Date(date.getTime() + 0x36ee80L * (long) count);
	}

	public static Date addDay(Date date, int count) {
		return new Date(date.getTime() + 0x5265c00L * (long) count);
	}

	public static Date addWeek(Date date, int count) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(3, count);
		return c.getTime();
	}

	public static Date addMonth(Date date, int count) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(2, count);
		return c.getTime();
	}

	public static Date addYear(Date date, int count) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(1, count);
		return c.getTime();
	}

	/**
	 * 指定日期是否在本周范围内
	 * 
	 * @param d
	 * @return
	 */
	public static boolean inCurrentWeek(Date d) {
		Date today = new Date();
		return between(d, getFirstDayOfWeek(today), getLastDayOfWeek(today));
	}

	/**
	 * 指定日期是否某日期范围内
	 * 
	 * @param d
	 * @return
	 */
	public static boolean between(Date date, Date date1, Date date2) {
		if (date1.after(date2)) {
			Date swap = date1;
			date1 = date2;
			date2 = swap;
		}
		return date.compareTo(date1) >= 0 && date.compareTo(date2) <= 0;
	}

	/**
	 * 获取当前日期,同时丢弃时间
	 * 
	 * @return
	 */
	public static Date getCurrentDate() {
		return Util.str2date(Util.getStdfDate());
	}

	/**
	 * 判断日期字符串是否合法
	 * 
	 * @param date
	 * @param format
	 * @return
	 */
	public static boolean validate(String date, String format) {
		if (format == null || "".equals(format)) {
			format = Util.STDDF;
		}
		SimpleDateFormat f1 = new SimpleDateFormat(format);
		f1.setLenient(false);
		try {
			f1.parse(date);
			return true;
		} catch (ParseException e) {
			return false;
		}
	}

	/**
	 * 将日期按照指定模式转换为字符串
	 * 
	 * @param date
	 *            日期
	 * @param pattern
	 *            指定模式
	 * @return 转换后的字符串
	 */
	public static String format(final Date date, final String pattern) {
		if (date != null) {
			// TimeZone tz = TimeZone.getTimeZone("ETC/GMT-8");
			// TimeZone.setDefault(tz);
			return new SimpleDateFormat(pattern).format(date);
		} else {
			return null;
		}
	}

	/**
	 * 使用预置的正则表达式来验证日期字符串<br>
	 * 
	 * @param date
	 *            待验证的日期字符串
	 * @param pattern
	 *            预置的日期格式正则表达式的名称或自定义正则表达式
	 * @return
	 */
	public static boolean matches(String date, String pattern) {
		Pattern p = patterns.get(pattern);
		if (p == null) {
			synchronized (patterns) {
				p = patterns.get(pattern);
				if (p == null) {
					p = patterns.put(pattern, Pattern.compile(pattern));
				}
			}
		}
		return p.matcher(date).matches();
	}

	/**
	 * 截到日，日以下全部置为0
	 * 
	 * @param date
	 * @return
	 */
	public static Date floor(Date date) {
		return DateUtil.floor(date, DatePart.DAY);
	}

	/**
	 * 截取到指定时间字段，其以下全置为0
	 * 
	 * @param date
	 * @param to
	 * @return
	 */
	public static Date floor(Date date, DatePart to) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		if (to.intValue <= DatePart.SEC.intValue) {
			c.set(Calendar.MILLISECOND, 0);
		}
		if (to.intValue <= DatePart.MIN.intValue) {
			c.set(Calendar.SECOND, 0);
		}
		if (to.intValue <= DatePart.HOUR.intValue) {
			c.set(Calendar.MINUTE, 0);
		}
		if (to.intValue <= DatePart.DAY.intValue) {
			c.set(Calendar.HOUR_OF_DAY, 0);
		}
		if (to.intValue <= DatePart.MONTH.intValue) {
			c.set(Calendar.DATE, 0);
		}
		if (to.intValue <= DatePart.YEAR.intValue) {
			c.set(Calendar.MONTH, 0);
		}
		return c.getTime();
	}

	/**
	 * 分别在年、月、日、时、分、秒、毫秒上加对应的值
	 * 
	 * @param date
	 *            原日期
	 * @param year
	 * @param month
	 * @param day
	 * @param hour
	 * @param minute
	 * @param second
	 * @param millsecond
	 */
	public static Date add(Date date, int year, int month, int day, int hour, int minute, int second, int millsecond) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.YEAR, year);
		c.add(Calendar.MONTH, month);
		c.add(Calendar.DATE, day);
		c.add(Calendar.HOUR, hour);
		c.add(Calendar.MINUTE, minute);
		c.add(Calendar.SECOND, second);
		c.add(Calendar.MILLISECOND, millsecond);
		return c.getTime();
	}

	/**
	 * 分别在年、月、日上加对应的值
	 * 
	 * @param date
	 * @param year
	 * @param month
	 * @param day
	 */
	public static Date add(Date date, int year, int month, int day) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.YEAR, year);
		c.add(Calendar.MONTH, month);
		c.add(Calendar.DATE, day);
		return c.getTime();
	}

	/**
	 * 
	 * 分别在时、分、秒、毫秒上加对应的值
	 * 
	 * @param date
	 * @param hour
	 * @param minute
	 * @param second
	 * @param millsecond
	 */
	public static Date add(Date date, int hour, int minute, int second, int millsecond) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.HOUR, hour);
		c.add(Calendar.MINUTE, minute);
		c.add(Calendar.SECOND, second);
		c.add(Calendar.MILLISECOND, millsecond);
		return c.getTime();
	}

	/**
	 * 将yyyyMMdd格式的字符串转换为日期
	 * 
	 * @param date
	 * @return
	 */
	public static Date yyyyMMdd(String date) {
		return Util.str2date(date, Util.STDDF2);
	}

	/**
	 * 将日期转换为yyyyMMdd格式的字符串
	 * 
	 * @param date
	 * @return
	 */
	public static String yyyyMMdd(Date date) {
		return Util.date2str(date, Util.STDDF2);
	}

	/**
	 * 将当前日期转换为yyyyMMdd格式的字符串
	 * 
	 * @return
	 */
	public static String yyyyMMdd() {
		return Util.date2str(new Date(), Util.STDDF2);
	}

	/**
	 * 将yyyyMMddHHmmss格式的字符串转换为日期
	 * 
	 * @param date
	 * @return
	 */
	public static Date yyyyMMddHHmmss(String date) {
		return Util.str2date(date, Util.STDDTF2);
	}

	/**
	 * 将日期转换为yyyyMMddHHmmss格式的字符串
	 * 
	 * @param date
	 * @return
	 */
	public static String yyyyMMddHHmmss(Date date) {
		return Util.date2str(date, Util.STDDTF2);
	}

	/**
	 * 将当前日期转换为yyyyMMddHHmmss格式的字符串
	 * 
	 * @param date
	 * @return
	 */
	public static String yyyyMMddHHmmss() {
		return Util.date2str(new Date(), Util.STDDTF2);
	}

	/**
	 * 比较两个日期在天上的差异<br>
	 * 注意：此方法与getDaysBetween不同，它可能返回负值，且0601 23:59:59 和 0602 00:00:00 之间相差一天
	 * 
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static long dayDiff(Date d1, Date d2) {
		return dateDiff(d1, d2, DatePart.DAY);
	}

	/**
	 * 返回两个日期相差的自然年月日时分秒<br>
	 * 
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static Long[] gaps(Date d1, Date d2) {
		Long[] ra = new Long[7];
		Arrays.fill(ra, 0L);
		if (null == d1 || null == d2) {
			return ra;
		}
		if (d1.after(d2)) {
			Date d = d1;
			d1 = d2;
			d2 = d;
		}
		Calendar c1 = Calendar.getInstance();
		c1.setTime(d1);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
		// 相差多少毫秒
		long ms1 = c1.get(Calendar.MILLISECOND);
		long ms2 = c2.get(Calendar.MILLISECOND);
		ra[6] = (ms2 >= ms1) ? (ms2 - ms1) : (1000 - ms1 + ms2);
		// 相差多少秒
		long s1 = c1.get(Calendar.SECOND);
		long s2 = c2.get(Calendar.SECOND) - (ms2 < ms1 ? 1 : 0);
		ra[5] = (s2 >= s1) ? (s2 - s1) : (60 - s1 + s2);
		// 相差多少分钟
		long m1 = c1.get(Calendar.MINUTE);
		long m2 = c2.get(Calendar.MINUTE) - (s2 < s1 ? 1 : 0);
		ra[4] = (m2 >= m1) ? (m2 - m1) : (60 - m1 + m2);
		// 相差多少小时
		long h1 = c1.get(Calendar.HOUR_OF_DAY);
		long h2 = c2.get(Calendar.HOUR_OF_DAY) - (m2 < m1 ? 1 : 0);
		ra[3] = (h2 >= h1) ? (h2 - h1) : (24 - h1 + h2);
		// 相差多少天
		long a1 = c1.get(Calendar.DAY_OF_MONTH);
		long a2 = c2.get(Calendar.DAY_OF_MONTH) - (h2 < h1 ? 1 : 0);
		ra[2] = (a2 >= a1) ? (a2 - a1) : (c1.getActualMaximum(Calendar.DAY_OF_MONTH) - a1 + a2);
		// 相差多少月
		long o1 = c1.get(Calendar.MONTH);
		long o2 = c2.get(Calendar.MONTH) - (a2 < a1 ? 1 : 0);
		ra[1] = (o2 >= o1) ? (o2 - o1) : (12 - o1 + o2);
		// 相差多少年
		long y1 = c1.get(Calendar.YEAR);
		long y2 = c2.get(Calendar.YEAR) - (o2 < o1 ? 1 : 0);
		ra[0] = y2 - y1;
		return ra;
	}

	/**
	 * 以要求的格式返回两个日期相差的自然年月日时分秒<br>
	 * 
	 * @param d1
	 * @param d2
	 * @param format
	 *            如："%d年 %d月 %d日 %d时 %d分 %d秒"
	 * @return
	 */
	public static String gaps(Date d1, Date d2, String format) {
		return String.format(format, (Object[]) gaps(d1, d2));
	}

	public static void main(String[] args) {
		// Date d1 = Util.str2date("2024-02-27 00:00:00", Util.STDDTF);
		// Date d2 = DateUtil.add(d1, 0, 11, 30, 0, 0, 0, 0);
		// System.out.println(Util.date2str(d2, Util.STDDTF));
		// Long g[] = DateUtil.gaps(d1, d2);
		// for (long l : g) {
		// System.out.print(l);
		// System.out.print(",");
		// }
		Date d1 = Util.str2date("20240731", Util.STDDF2);
		Date d2 = Util.str2date("20250722", Util.STDDF2);
		Long g[] = DateUtil.gaps(d1, d2);
		for (int i = 0; i < g.length; i++) {
			System.out.println(g[i]);
		}
	}
}
